package com.huawei.drive.activity;

import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.huawei.cloud.base.auth.DriveCredential;
import com.huawei.cloud.base.http.FileContent;
import com.huawei.cloud.base.util.StringUtils;
import com.huawei.cloud.client.exception.DriveCode;
import com.huawei.cloud.services.drive.Drive;
import com.huawei.cloud.services.drive.model.File;
import com.huawei.cloud.services.drive.model.FileList;
import com.huawei.drive.MyApplication;
import com.huawei.drive.R;
import com.huawei.drive.adapter.QueryResultAdapter;
import com.huawei.drive.base.BaseActivity;
import com.huawei.drive.hms.CredentialManager;
import com.huawei.drive.hms.HmsProxyImpl;
import com.huawei.drive.task.DriveTask;
import com.huawei.drive.task.TaskManager;
import com.huawei.drive.utlis.FontsUtils;
import com.huawei.drive.utlis.MyFileUtils;
import com.huawei.hmf.tasks.Task;
import com.huawei.hms.common.ApiException;
import com.huawei.hms.framework.common.Logger;
import com.huawei.hms.support.hwid.HuaweiIdAuthManager;
import com.huawei.hms.support.hwid.result.AuthHuaweiId;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends BaseActivity {

    private static final int REQUEST_CODE_UPLOAD = 1001;
    // 1002 Occupied  HmsProxyImpl.REQUEST_SIGN_IN_LOGIN
    private static final int REQUEST_CODE_ERMISSIONS = 1003;
    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.bt_login_upload)
    Button btLoginUpload;

    @BindView(R.id.am_rv)
    RecyclerView amRv;


    private SearchView mSearchView;


    // This is the permission to apply
    private static String[] PERMISSIONS_CAMERA_AND_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA};

    private static final Map<String, String> MIME_TYPE_MAP = new HashMap<String, String>();

    static {
        MIME_TYPE_MAP.put(".doc", "application/msword");
        MIME_TYPE_MAP.put(".jpg", "image/jpeg");
        MIME_TYPE_MAP.put(".mp3", "audio/x-mpeg");
        MIME_TYPE_MAP.put(".mp4", "video/mp4");
        MIME_TYPE_MAP.put(".pdf", "application/pdf");
        MIME_TYPE_MAP.put(".png", "image/png");
        MIME_TYPE_MAP.put(".txt", "text/plain");
    }

    private QueryResultAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);
        initView();
    }

    private void initView() {
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        amRv.setLayoutManager(gridLayoutManager);

    }

    /**
     * Solve the problem that Android 6.0 and above cannot read external storage permissions
     *
     * @param activity
     * @param requestCode
     * @return
     */
    public static boolean isGrantExternalRW(Activity activity, int requestCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            int storagePermission = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            int cameraPermission = activity.checkSelfPermission(Manifest.permission.CAMERA);
            // Check if there is permission, if you do not have permission, you need to apply
            if (storagePermission != PackageManager.PERMISSION_GRANTED ||
                    cameraPermission != PackageManager.PERMISSION_GRANTED) {
                // request for access
                activity.requestPermissions(PERMISSIONS_CAMERA_AND_STORAGE, requestCode);
                // Returns false. Description no authorization
                return false;
            }
        }
        return true;
    }

    private void showTips(final String toastText) {
        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_LONG).show();
//                tvTips.setText(toastText);
//                //获取剪贴板管理器：
//                ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
//// 将ClipData内容放到系统剪贴板里。
//                cm.setPrimaryClip(ClipData.newPlainText("Label", toastText));

            }
        });
    }

    private File fileSearched;


    /**
     * Search for files.
     * https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/drivekit-nop-client-development
     * https://developer.huawei.com/consumer/en/doc/drivekit-server-api-fileslist
     *
     * @param query    Query parameter. For details, please refer to Q statements.
     * @param orderBy  Sort key.
     * @param pageSize Maximum number of files to return per page.
     * @param fields   Fields to be contained in the response.
     */
    private List<File> getFileList(String query, String orderBy, int pageSize, String fields) {
        List<File> fileList = null;
        try {
            Drive drive = buildDrive();
            Drive.Files.List request = drive.files().list();
            String cursor = null;
            fileList = new ArrayList<>();

            do {
                FileList result = null;
                result = request.setQueryParam(query)
                        .setOrderBy(orderBy)
                        .setPageSize(pageSize)
                        .setFields(fields)
                        .execute();
                for (File file : result.getFiles()) {
                    fileList.add(file);
                }
                cursor = result.getNextCursor();
                request.setCursor(cursor);
            } while (!StringUtils.isNullOrEmpty(cursor));
        } catch (Exception e) {
            Logger.e(TAG, "executeFilesList exception: " + e.toString());
        }
        return fileList;
    }

    /**
     * Querying uploaded files
     * @param type 1 Query all 2 Exact keyword search  3 Keyword contains query
     * @param keyword
     */
    private void queryFiles(int type, String keyword) {
        btLoginUpload.setEnabled(false);
        String accessToken = HmsProxyImpl.getInstance().getAccessToken();
        new Thread(new Runnable() {
            @Override
            public void run() {

                if (accessToken == null) {
                    showTips("please click 'Login'.");
                    return;
                }
                if ((type == 2 || type == 3) && StringUtils.isNullOrEmpty(keyword)) {
                    showTips("please input filename");
                    return;
                }
                String query = "";
                //=,!=,contains

                if (type == 1) {
                    query = "mimeType != 'application/vnd.huawei-apps.folder'";
                } else if (type == 2) {
                    query = "fileName = '" + keyword + "' and mimeType != 'application/vnd.huawei-apps.folder'";
                } else if (type == 3) {
                    query = "fileName contains '" + keyword + "' and mimeType != 'application/vnd.huawei-apps.folder'";
                }
                String fields = "category,nextCursor,files/id,files/fileName,files/size,files/fileSuffix,files/mimeType";
//                String orderBy = "fileName";
                String orderBy = "createdTime";
                int pageSize = 100;
                List<File> resFileList = getFileList(query, orderBy, pageSize, fields);


                if (resFileList != null && resFileList.size() > 0) {
                    mAdapter = new QueryResultAdapter(resFileList);
                    amRv.post(new Runnable() {
                        @Override
                        public void run() {
                            amRv.setAdapter(mAdapter);
                            btLoginUpload.setEnabled(true);
                            showTips("query ok");
                        }
                    });

                } else {
                    amRv.post(new Runnable() {
                        @Override
                        public void run() {
                            btLoginUpload.setEnabled(true);
                            showTips("No more data");
                        }
                    });
                }


            }
        }).start();
    }
    /**
     * https://developer.huawei.com/consumer/en/doc/drivekit-server-api-filescreate
     * https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/drivekit-nop-client-development
     * @param path
     */
    private void uploadFiles(String path) {
        String accessToken = HmsProxyImpl.getInstance().getAccessToken();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {

                    if (accessToken == null) {
                        showTips("please click 'Login'.");
                        return;
                    }
                    if (TextUtils.isEmpty(path)) {
                        showTips("Please select an uploaded file");
                        return;
                    }
                    java.io.File fileObject = new java.io.File(path);
                    if (!fileObject.exists()) {
                        showTips("the input file does not exit.");
                        return;
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            btLoginUpload.setEnabled(false);
                        }
                    });
                    Drive drive = buildDrive();
                    Map<String, String> appProperties = new HashMap<>();
                    appProperties.put("appProperties", "property");
                    // create  directory
                    File file = new File();
                    file.setFileName("somepath" + System.currentTimeMillis())
                            .setMimeType("application/vnd.huawei-apps.folder")
                            .setAppSettings(appProperties);
                    File directoryCreated = drive.files().create(file).execute();
                    // create file on cloud
                    String id = directoryCreated.getId();
                    File content = new File()
                            .setFileName(fileObject.getName())
                            .setMimeType(mimeType(fileObject))
                            .setParentFolder(Collections.singletonList(id));
                    
                    drive.files()
                            .create(content, new FileContent("image/jpeg", fileObject))
                            .setFields("*")
                            .execute();

                    showTips("upload success");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            btLoginUpload.setEnabled(true);
                        }
                    });
                    queryFiles(1, "");
                } catch (Exception ex) {

                    showTips("upload error " + ex.toString());
                }
            }
        }).start();
    }

    private Drive buildDrive() {
        Drive service = new Drive.Builder(CredentialManager.getInstance().getCredential(), this).build();
        return service;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ERMISSIONS:
                if (grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Verify that the permission is obtained. If the permission is obtained,
                    // the external storage will be open and a toast prompt will pop up to obtain authorization.
                    String sdCard = Environment.getExternalStorageState();
                    if (sdCard.equals(Environment.MEDIA_MOUNTED)) {
                        HmsProxyImpl.getInstance().singIn(this);
                    }
                } else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "Permissions Deny", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
                break;
            default:
                break;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    /**
     * init dev login view
     */
    private void initDevLoginView() {

        String accessToken = HmsProxyImpl.getInstance().getAccessToken();
        //no longin
        if (TextUtils.isEmpty(accessToken)) {
            btLoginUpload.setText(R.string.login);
        } else {
            btLoginUpload.setText(R.string.upload);
        }

    }



    private String _getPath(Intent data) {
        Uri uri = data.getData();
        if ("file".equalsIgnoreCase(uri.getScheme())) {//使用第三方应用打开
            return uri.getPath();
        }
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
            return MyFileUtils.getPath(this, uri);
        } else {//4.4以下下系统调用方法
            return MyFileUtils.getRealPathFromURI(this, uri);
        }
    }



    // 打开系统的文件选择器
    public void pickFile() {
//        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//        intent.addCategory(Intent.CATEGORY_OPENABLE);
//        intent.setType("*/*");
//        startActivityForResult(intent, REQUEST_CODE_UPLOAD);

        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("*/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        try {
            startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), REQUEST_CODE_UPLOAD);
        } catch (ActivityNotFoundException ex) {
            // Potentially direct the user to the Market with a Dialog
            Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show();
        }
    }
    /**
     refreshAccessToken
     */
    private  DriveCredential.AccessMethod refreshAT = new DriveCredential.AccessMethod() {
        @Override
        public String refreshToken() {
            return HmsProxyImpl.getInstance().refreshAccessToken();
        }
    };
    /**
     * Init Drive
     */
    private void initDrive() {
        final String unionID = HmsProxyImpl.getInstance().getUnionId();
        final String at = HmsProxyImpl.getInstance().getAccessToken();
        if (TextUtils.isEmpty(unionID) || TextUtils.isEmpty(at)) {
            Log.e(TAG, "initDrive error, unionID or at is null: " + "unionID:" + unionID + " at " + at);
            return;
        }
        /**
         * Refresh acccess token method for Drive sdk
         */

        // CredentialManager.getInstance().init must be called in a thread, and need to handle the results returned by the Drive SDK initialization
        TaskManager.getInstance().execute(new DriveTask() {
            @Override
            public void call() {
                int returnCode = CredentialManager.getInstance().init(unionID, at, refreshAT);
                if (DriveCode.SUCCESS == returnCode) {
                    // Jump to the app home page after successful initialization.
                    Log.e(TAG, "call: DriveCode.SUCCESS");
                    MainActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            initDevLoginView();
                            queryFiles(1, "");
                        }
                    });


                } else if (DriveCode.SERVICE_URL_NOT_ENABLED == returnCode) {
                    showTips("drive is not enabled");
                } else {
                    showTips("drive init error");

                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_toolbar_search_view, menu);
        initSearch(menu);
        return true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        HmsProxyImpl.getInstance().cancelAuthorization(this);
    }

    private static final String TAG = "MainActivity";

    /**
     * 初始化搜索框
     *
     * @param menu
     */
    private void initSearch(Menu menu) {
        MenuItem searchItem = menu.findItem(R.id.menu_search_view);
        mSearchView = (SearchView) searchItem.getActionView();
        mSearchView.setSubmitButtonEnabled(true);

        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                mSearchView.clearFocus();
                queryFiles(3, s);
                return true;
            }

            @Override
            public boolean onQueryTextChange(String s) {
//                Log.e(TAG, "onQueryTextSubmit: " + s);
                return true;
            }
        });
    }

    @OnClick(R.id.bt_login_upload)
    public void onViewClicked() {
        btLoginUpload.setEnabled(false);
        String accessToken = HmsProxyImpl.getInstance().getAccessToken();
        //没有登录
        if (TextUtils.isEmpty(accessToken)) {
            if (!isGrantExternalRW(this, REQUEST_CODE_ERMISSIONS)) {
                Log.i(TAG, "Permissions Deny");
            } else {
                // Call singIn method
                HmsProxyImpl.getInstance().singIn(this);
            }
        } else {
            pickFile();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.i(TAG, "onActivityResult, requestCode = " + requestCode + ", resultCode = " + resultCode);
        try {
            // Handle HMS SDK authentication sign in callback results
            if (requestCode == HmsProxyImpl.REQUEST_SIGN_IN_LOGIN) {
                btLoginUpload.setEnabled(true);
                // login success, get user message by getSignedInAccountFromIntent
                Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
                if (authHuaweiIdTask.isSuccessful()) {
                    AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
                    HmsProxyImpl.getInstance().dealSignInResult(huaweiAccount);
                    initDrive();
                } else {
                    // login failed
                    Log.i(TAG, "onActivityResult, signIn failed: " + ((ApiException) authHuaweiIdTask.getException()).getStatusCode());
                    Toast.makeText(getApplicationContext(), "onActivityResult, signIn failed.", Toast.LENGTH_LONG).show();
                }
            } else if (requestCode == REQUEST_CODE_UPLOAD) {
                if (data == null) {
                    btLoginUpload.setEnabled(true);

                    // not select any files
                    Log.i(TAG, "The user did not select any files and returned directly");
                    return;
                }
                String path = _getPath(data);
                if (TextUtils.isEmpty(path)) {
                    showTips("Incorrect file selection");
                    return;
                }

                uploadFiles(path);

            }
        } catch (Exception e) {

            Log.i(TAG, "onActivityResult, catch Exception");
        }
    }

    private String mimeType(java.io.File file) {
        if (file != null && file.exists() && file.getName().contains(".")) {
            String fileName = file.getName();
            String suffix = fileName.substring(fileName.lastIndexOf("."));
            if (MIME_TYPE_MAP.keySet().contains(suffix)) {
                return MIME_TYPE_MAP.get(suffix);
            }
        }
        return "*/*";
    }
}
